<?php

	// +----------------------------------------------------------------------
	// | 行为事件
	// +----------------------------------------------------------------------
	// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
	// +----------------------------------------------------------------------
	// | Author: 微尘 <yicmf@qq.com>
	// +----------------------------------------------------------------------

	namespace app\event\ucenter;

	use app\common\event\Base;
	use app\model\ucenter\Action as ActionModel;
	use app\model\ucenter\User as UserModel;
	use app\model\ucenter\ActionLog as ActionLogModel;
	use app\model\ucenter\ActionLimit as ActionLimitModel;
	use think\Container;
	use think\facade\Db;
	use think\Exception;
	use think\facade\App;
	use think\facade\Config;
	use think\facade\Log;
	use think\Model;

	class Action extends Base
	{
		/**
		 * 新增|更新
		 * @param array $param
		 * @param UserModel $user
		 */
		public function update($param, $user = null)
		{
			try {
				if (!empty($param['id'])) {
					$action = ActionModel::get($param['id']);
					$action['name'] = $param['name'];
					$action['title'] = $param['title'];
					$action['remark'] = $param['remark'];
//					$action['action_rule'] = $param['action_rule'];
					$action['log_rule'] = $param['log_rule'];
					$action['is_open'] = $param['is_open'];
					if (!$action->save()) {
						throw new Exception('数据储存失败');
					}
				} else {
					$action['name'] = $param['name'];
					$action['title'] = $param['title'];
					$action['remark'] = $param['remark'];
//					$action['action_rule'] = $param['action_rule'];
					$action['log_rule'] = $param['log_rule'];
					$action['is_open'] = $param['is_open'];
					if (!ActionModel::create($action)) {
						throw new Exception('新建行为失败');
					}
				}
				$data['code'] = 0;
			} catch (Exception $e) {
				$data['code'] = 1;
				$data['message'] = $e->getMessage();
			}
			return $data;
		}


		/**
		 * 清理日志
		 * @return array
		 */
		public function clear()
		{
			try {
				$result = ActionLogModel::where('status', 1)
					->whereTime('create_time', '<', '-' . Config::get('setting.log_max_time') . ' days')
					->update(['status'=>-2]);
				if (!$result) {
					throw new Exception('暂无过期日志');
				}
				$data['code'] = 0;
				$data['message'] = '成功删除' . $result . '条日志';
			} catch (Exception $e) {
				$data['code'] = 1;
				$data['message'] = $e->getMessage();
			}
			return $data;
		}


		/**
		 * 行为限制
		 * @param $name
		 * @param $user
		 * @return array
		 */
		public static function limit($name, $user = null)
		{
			try {
				// 查询行为,判断是否执行
				$action = ActionModel::where('name', $name)->where('status', 1)->find();
				if (!$action) {
					throw new Exception('执行的日志[' . $action . ']行为不存在');
				}
				//  日志限制
				if ($action['frequency'] > 0 && $action['cycle_num'] > 0) {
					if ($user) {
						$frequency = $action->logs()
							->where('user_id', $user['id'])
							->whereTime('create_time', '>', '-' . $action['cycle_num'] . ' ' . $action['cycle'])
							->where('status', 1)->count();
					} else {
						$frequency = $action->logs()
							->where('ip', $request->ip())
							->whereTime('create_time', '>', '-' . $action['cycle_num'] . ' ' . $action['cycle'])
							->where('status', 1)->count();
					}
					if ($frequency > $action['frequency']) {
						throw new Exception($action['punish_message'] ?: '超频操作');
					}
				}
				$data['code'] = 0;
			} catch (Exception $e) {
				$data['code'] = 1;
				$data['message'] = $e->getMessage();
			}
			return $data;
		}

		/**
		 * 记录行为日志，并执行该行为的规则
		 * @param string $name 行为标识
		 * @param string|model $model 触发行为的模型名
		 * @param string|model $option 可替换参数
		 * @return  array
		 * @author  : 微尘 <yicmf@qq.com>
		 */
		public static function log($name, $model, $option = [])
		{
			try {
				// 参数检查
				if (empty($name) || empty($model)) {
					throw new Exception('参数不能为空');
				}
				// 查询行为,判断是否执行
				$action = ActionModel::where('name', $name)->where('status', 1)->find();
				if (!$action) {
					throw new Exception('执行的日志[' . $action . ']行为不存在');
				}
				if (0 == $action['is_open']) {
					throw new Exception('当前记录已经关闭');
				}
				$request = app('request');
				$user = $request->user;
				$param = $request->param();
				// 插入行为日志
				$log = [];
				if (isset($option['id'])) {
					$log['model_id'] = $option['id'];
				}
				if (is_string($model)) {
					$log['model'] = $model;
				} else {
					$log['model'] = $model->getName();
					$log['model_id'] = $model['id'];
				}
				$log['user_id'] = $user ? $user['id'] : null;
				$log['request_action'] = $request->action();
				$log['request_controller'] = $request->controller();
				$log['request_module'] = isset($option['module'])?$option['module']: request()->auth_module;;
				$log['action_status'] = isset($option['status']) ? $option['status'] : 1;
				$log['url'] = $request->url(true);

				if (!empty($option) && is_string($option)) {
					$log['message'] = $option;
				} else {
					if (!empty($action['log_rule'])) {
						if (false !== strpos($action['log_rule'], '{')) {
							$view = app('view');
							$action['log_rule'] = $view->display($action['log_rule'], [
								'option' => $option,
								'request_action' => $request->action(),
								'request_controller' => $request->controller(),
								'request_module' =>request()->auth_module,
								'param' => $param,
								'user' => $user,
								'model' => $model
							]);
						}
						$log['message'] = $action['log_rule'];
					} else {
						// 未定义日志规则，记录操作url
						$log['message'] = '操作url：' . $request->url(true);
					}
				}
				$log_save = $action->logs()->save($log);
				// 保存日志
				if (!$log_save) {
					throw new Exception('日志行为日志写入异常，写入数据:' . var_export($log, true));
				}
				$data = [];
				$data['code'] = 0;
			} catch (Exception $e) {
				Log::record($e->getMessage());
				$data['code'] = 1;
				$data['file'] = $e->getFile();
				$data['line'] = $e->getLine();
				$data['message'] = $e->getMessage();
			}
			return $data;
		}

	}
